Create Shiny Apps with non-default layouts.
Let’s start with a blank Shiny app (shinyapp {snippet})
library(shiny)
ui <- fluidPage(
)
server <- function(input, output) {
}
shinyApp(ui = ui, server = server)It works, but it’s not very nice looking or “customized”.
library(shiny)
library(ggplot2)
ui <- fluidPage(
varSelectInput("var", "Which Variable?", data = mtcars),
plotOutput("plot")
)
server <- function(input, output) {
output$plot <- renderPlot({
ggplot(mtcars, aes(x = !!input$var)) +
geom_histogram(bins = 20)
})
}
shinyApp(ui = ui, server = server)
Today, we will explore how to make your UI layouts more sophisticated than just a sequence of elements.
fluidPage() function.
fluidPage() are functions which together specify the UI layout of your app.navbarPage().dashboardPage(): https://rstudio.github.io/shinydashboard/titlePanel()```r
library(shiny)
ui <- fluidPage(
titlePanel("My First Title", windowTitle = "I am the Window Title")
)
server <- function(input, output) {
}
shinyApp(ui = ui, server = server)
```
Running the app, you should get something like this:
fluidPage() Grid Layout with fluidRow() and column().fluidPage() layout is really a grid of rows which have columns with an assumed total browser width of 12 units
fluidRow() and column() define the layout of a fluidPage().
column() allocates horizontal space within the 12-unit wide grid.fluidRow()
column() calls as input.column() calls as you want separate columns (max 12).column()
fluidRow().width).
column() calls must equal 12.Hadley’s Graphic:
fluidRow() and column()Second Row: three output columns: each with one pol: a point plot and two histograms.
library(shiny)
library(ggplot2)
ui <- fluidPage(
fluidRow(title = "Inputs",
column(6,
varSelectInput("var1", "Variable 1", data = mtcars),
varSelectInput("var2", "Variable 2", data = mtcars)
),
column(6,
sliderInput("bins", "Number of Bins", min = 1, max = 50, value = 20)
)
),
fluidRow(title = "Outputs",
column(4,
plotOutput("plot1")
),
column(4,
plotOutput("plot2")
),
column(4,
plotOutput("plot3")
)
)
)
server <- function(input, output) {
output$plot1 <- renderPlot({
ggplot(mtcars, aes(x = !!input$var1, y = !!input$var2)) +
geom_point()
})
output$plot2 <- renderPlot({
ggplot(mtcars, aes(x = !!input$var1)) +
geom_histogram(bins = input$bins)
})
output$plot3 <- renderPlot({
ggplot(mtcars, aes(x = !!input$var2)) +
geom_histogram(bins = input$bins)
})
}
shinyApp(ui = ui, server = server)Running the app, you should get something like this:
Note: You can nest fluidRow()s inside fluidRow()s so it can get quite complicated.
Create a grid layout of four squares where the top left square takes as input two variables of the iris dataset to include in a scatterplot and the bottom right contains the resulting scatterplot, color-coded by species. The top right square and bottom left squares should remain empty. Have the second variable default to Sepal.Width.
Your final app should look like this:
tabsetPanel() and tabPanel()tabsetPanel() and tabPanel().tabsetPanel()- Arguments include calls to `tabPanel()` calls.
- You place it as an argument in either `mainPanel()` in the sidebar layout,
or in one of the `column()` calls in the grid layout.
tabPanel()- Takes as input different input/output elements, separated by a comma.
- Each element will get its own tab.
- Needs to be placed in `tabsetPanel()`.
Here is an example from the mtcars dataset, where the tabs have different plots for the variables we select.
library(shiny)
library(ggplot2)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
varSelectInput("var1", "Variable 1", data = mtcars),
varSelectInput("var2", "Variable 2", data = mtcars),
sliderInput("bins", "Number of Bins", min = 1, max = 50, value = 20)
),
mainPanel(
tabsetPanel(
tabPanel("Scatterplot",
plotOutput("plot1")
),
tabPanel("Histogram of Variable 1",
plotOutput("plot2")
),
tabPanel("Histogram of Variable 2",
plotOutput("plot3")
)
)
)
)
)
server <- function(input, output) {
output$plot1 <- renderPlot({
ggplot(mtcars, aes(x = !!input$var1, y = !!input$var2)) +
geom_point()
})
output$plot2 <- renderPlot({
ggplot(mtcars, aes(x = !!input$var1)) +
geom_histogram(bins = input$bins)
})
output$plot3 <- renderPlot({
ggplot(mtcars, aes(x = !!input$var2)) +
geom_histogram(bins = input$bins)
})
}
shinyApp(ui = ui, server = server)Running the app, you should get something like this:
iris dataset.
geom_smooth()).A good default value for the bandwidth might be 0.25 in this case.
Your app should look like this:
wellPanel() to group elements together in a slightly inset border.wellPanel()
library(shiny)
library(ggplot2)
ui <- fluidPage(
wellPanel(
sliderInput("bins", "How many bins?", min = 1, max = 50, value = 20),
plotOutput("hist")
)
)
server <- function(input, output, session) {
output$hist <- renderPlot({
ggplot(mtcars, aes(x = mpg)) +
geom_histogram(bins = input$bins)
})
}
shinyApp(ui, server)
absolutePanel().conditionalPanel().fixedPanel().headerPanel().inputPanel().navlistPanel().shinytheme("theme_name")If you know or learn CSS, you can do some extreme customization of the look and feel of your Shiny App.
We will not learn CSS but we can explore the shinythemes package!
The shinythemes package gives you access to many different themes available in [Bootstrap](https://en.wikipedia.org/wiki/Bootstrap_(front-end_framework%29).
fluidPage()Inside fluidPage(), list the theme argument to be shinytheme("theme_name"), where "theme_name" is one of the themes that comes with shinythemes.
The full list of available themes can be found by
help("shinythemes")Example:
library(shiny)
library(shinythemes)
ui <- fluidPage(theme = shinytheme("darkly"),
sidebarLayout(
sidebarPanel(
sliderInput("number", "select a number", 0, 100, 40)
),
mainPanel(
tabsetPanel(
tabPanel("a"),
tabPanel("b"),
tabPanel("c")
)
)
)
)
server <- function(input, output, session) {
}
shinyApp(ui, server)
The fresh R package provides a lot of customization of the Bootstrap and Bootswatch, which Shiny uses for its appearance.
library(fresh)app.R file for a Shiny App
create_theme() call.create_theme() arguments you should use:
theme: What theme do you wish to customize? Say "default" for the default Shiny theme.
help("shinythemes").output_file: The location to put the customized formatting file. This should end with “.css” since it will be a CSS file.
You must place the output file in a “www” sub-directory of your Shiny App.
bs_vars_*().
bs_vars_global() adjusts the global environment of the Shiny App (default text color, background color, the presence of a border, etc).create_theme(
theme = "default",
bs_vars_color(
gray_base = "#354e5c",
),
bs_vars_wells(
bg = "#FFF",
border = "#3f2d54"
),
bs_vars_global(
body_bg = "#e5ffe5"
),
output_file = "www/mytheme.css"
)You can get those hexadecimal colors by either googling “color wheel” or looking up the common web colors: http://websafecolors.info/color-chart
fluidPage(), you then give the theme argument the path to the CSS file.
You don’t need to say “www/mytheme.css” since Shiny will make the contents of the www directory available in the working directory.
ui <- fluidPage(
theme = "mytheme.css",
...
)library(shiny)
library(shinythemes)
library(fresh)
library(ggplot2)
create_theme(
theme = "default",
bs_vars_color(
gray_base = "#354e5c"
),
bs_vars_wells(
bg = "#90ee90",
border = "#552D42"
),
bs_vars_global(
body_bg = "#e5ffe5"
),
bs_vars_input(
color = "#5d3954",
border_radius="20px"
),
#
output_file = "www/mytheme.css"
)
ui <- fluidPage(
theme = "mytheme.css",
titlePanel("Old Faithful Geyser Data"),
sidebarLayout(
sidebarPanel(
wellPanel("This is a well Panel",
textInput("plot_title", "Plot Title?", value = "Your Title"),
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30)
)
),
mainPanel(
plotOutput("distPlot")
)
)
)
server <- function(input, output) {
output$distPlot <- renderPlot({
ggplot(faithful, aes(x = waiting)) +
geom_histogram(bins = input$bins, fill = "palegreen4") +
theme(plot.background = element_rect(fill = "palegreen1"))+
ggtitle(input$plot_title) +
theme(
panel.background = element_rect(fill = "palegreen1",
colour = "palegreen1",
size = 0.5, linetype = "solid"),
panel.grid.major = element_line(size = 0.5, linetype = 'solid',
colour = "white"),
panel.grid.minor = element_line(size = 0.25, linetype = 'solid',
colour = "white")
)
})
}
shinyApp(ui = ui, server = server)
"Times New Roman".
library(help = "fresh").